﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Primitives;
using System.Security.Claims;
using System.Text.Json;
using WebApplication1.Cache;
using WebApplication1.Data;

namespace WebApplication1.Security
{
    public class RedisAuthenticationHandler : IAuthenticationHandler
    {
        private AuthenticationScheme Scheme;
        private HttpContext Context;
        private RedisAuthUser _redisAuthUser;
        private readonly RedisHelper _redisHelper;

        public RedisAuthenticationHandler(RedisAuthUser redisAuthUser,
            RedisHelper redisHelper)
        {
            _redisAuthUser = redisAuthUser;
            _redisHelper = redisHelper;
        }

        public Task<AuthenticateResult> AuthenticateAsync()
        {
            Context.Request.Headers.TryGetValue("session_id", out StringValues sessionIds);
            var sessionId = sessionIds.FirstOrDefault();
            if (string.IsNullOrWhiteSpace(sessionId))
                return Task.FromResult(AuthenticateResult.Fail("RedisAuthenticationHandler not find sessionId in headers!"));
            //redis根据sessionid查找用户数据
            if (!_redisHelper.KeyExists(sessionId))
                return Task.FromResult(AuthenticateResult.Fail("authentication is fail!"));
            try
            {
                var user = JsonSerializer.Deserialize<RedisAuthUser>(_redisHelper.GetValue(sessionId));
                _redisAuthUser.SetUser(user);
                return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), Scheme.Name)));
            }
            catch (Exception ex)
            {
                //反序列化失败
                return Task.FromResult(AuthenticateResult.Fail("authentication is fail!"));
            }
        }
        public Task ChallengeAsync(AuthenticationProperties? properties)
        {
            Context.Response.StatusCode = 401;
            return Task.CompletedTask;
        }

        public Task ForbidAsync(AuthenticationProperties? properties)
        {
            Context.Response.StatusCode = 403;
            return Task.CompletedTask;
        }

        public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
        {
            if (scheme == null)
            {
                throw new ArgumentNullException(nameof(scheme));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            Scheme = scheme;
            Context = context;
            return Task.CompletedTask;
        }
    }
}
